class_name Player
extends CharacterBody2D

const INTERACT_TIP = preload("res://levels/interact_tip/interact_tip.tscn")
var interact_tip_inst: Node2D = null

var actual_pos: Vector2 = Vector2.ZERO
var actual_velocity: Vector2 = Vector2.ZERO

@onready var state_machine: StateMachine = $StateMachine
@onready var animated_sprite_2d: AnimatedSprite2D = $AnimatedSprite2D
@onready var interact_area: Area2D = $InteractArea
@onready var body_collision_shape_2d: CollisionShape2D = $BodyCollisionShape2D

@export_category("state")
@export var init_state: String = "Normal"

@export_category("move")
@export var move_speed: int = 1
@export var dash_speed: int = 2
@export var dash_anim_scale: float = 1.5


func _ready() -> void:
	actual_pos = position
	
	if init_state:
		state_machine.transition(init_state)
		

func set_pos(pos):
	position = pos
	actual_pos = position
		

func get_face():
	return animated_sprite_2d.flip_h
	

func set_face(face):
	animated_sprite_2d.flip_h = face


func process_move(delta):
	var horizontal = Input.get_axis("move_left", "move_right")
	var vertical = Input.get_axis("move_up", "move_down")
	var is_dash = Input.is_action_pressed("dash")
	
	if horizontal != 0: horizontal = sign(horizontal)
	if vertical != 0: vertical = sign(vertical)
	
	if GameManager.player_input_locked:
		horizontal = 0
		vertical = 0
		is_dash = false
	
	var speed = move_speed if not is_dash else dash_speed
	var dir = Vector2(horizontal, vertical)
	actual_velocity = dir * speed
	
	var next_actual_pos_x = actual_pos.x + actual_velocity.x
	if is_body_collision(Vector2(next_actual_pos_x, actual_pos.y)):
		next_actual_pos_x = actual_pos.x
	
	var next_actual_pos_y = actual_pos.y + actual_velocity.y
	if is_body_collision(Vector2(actual_pos.x, next_actual_pos_y)):
		next_actual_pos_y = actual_pos.y
	
	actual_pos = Vector2(next_actual_pos_x, next_actual_pos_y)
	
	position = actual_pos

	if dir:
		if dir.x:
			animated_sprite_2d.flip_h = dir.x < 0
		
		if abs(actual_velocity.y) > abs(actual_velocity.x):
			if actual_velocity.y < 0:
				animated_sprite_2d.play("walk_up")
			else:
				animated_sprite_2d.play("walk_down")
		else:
			animated_sprite_2d.play("walk_side")
		
		if is_dash: animated_sprite_2d.speed_scale = dash_anim_scale
		else: animated_sprite_2d.speed_scale = 1.0
		
	else:
		animated_sprite_2d.play("idle")
	

func is_body_collision(test_position):
	var space_state = get_world_2d().direct_space_state
	
	var query = PhysicsShapeQueryParameters2D.new()
	query.shape = body_collision_shape_2d.shape
	
	var transform = body_collision_shape_2d.global_transform
	transform.origin = test_position
	query.transform = transform
	
	query.collide_with_bodies = true
	query.collision_mask = 1
	
	var results = space_state.intersect_shape(query)
	return results.size() > 0
		

func process_interact():	
	if GameManager.player_input_locked: 
		destroy_interact_tip()
		return
	
	var areas = interact_area.get_overlapping_areas()
	if areas.size() <= 0: 
		destroy_interact_tip()
		return
	
	var interact_target = areas[0].source
	
	if interact_target.has_method("interact"):
		show_interact_tip(interact_target)
	
	if interact_target.has_method("interactAuto"):
		interact_target.call("interactAuto")
	elif Input.is_action_just_pressed("interact") and interact_target.has_method("interact"):
		interact_target.call("interact")
		

func destroy_interact_tip():
	if interact_tip_inst: 
		interact_tip_inst.queue_free()
		interact_tip_inst = null
	

func show_interact_tip(target: Node2D):
	if not interact_tip_inst: 
		interact_tip_inst = INTERACT_TIP.instantiate()
		TransferManager.current_scene.add_child(interact_tip_inst)
	
	interact_tip_inst.global_position = target.global_position
